package org.stragma.symbian.aterms;

import aterm.*;

/**
 * This class is used to calculate the maximum depth
 * of an ATerm tree (Graphs are not supported) at this stage
 * @author Shirren
 *
 */
public class ATermTreeDepth implements IATermTreeDepth {
	
	/*
	 * Constructor
	 */
	public ATermTreeDepth() {
	}
	
	/**
	 * Get's the maximum depth from the given term in a tree
	 */
	@Override
	public long getMaximumDepth(ATerm term) {
		long depth = 0, maxDepth = 0;
		
		// If a term has been annotated with other terms
		// Incorporate this into the depth calculation
		ATermList annotations = term.getAnnotations();
		if ((annotations != null) && (!annotations.isEmpty())){
			maxDepth = this.getMaximumDepth(annotations);
		}
				
		switch (term.getType()) {
			
			case ATerm.INT:
			case ATerm.REAL:
			case ATerm.BLOB:
				
				return maxDepth > 1 ? maxDepth : 1;
				
			case ATerm.APPL:
				
				ATermAppl appl = (ATermAppl)term;
				int arity = appl.getArity();
				
				for(int i = 0; i < arity; i++) {
					depth = this.getMaximumDepth(appl.getArgument(i));
					if (depth > maxDepth) {
						maxDepth = depth;
					}
				}
				
				return maxDepth + 1;
				
			case ATerm.LIST:
				
				ATermList list = (ATermList)term;
				while(!list.isEmpty()) {
					depth = this.getMaximumDepth(list.getFirst());
					
					if (depth > maxDepth) {
						maxDepth = depth;
					}
					
					list = list.getNext();
				}
				
				return maxDepth + 1;
				
			case ATerm.PLACEHOLDER:
				
				ATermPlaceholder holder = (ATermPlaceholder)term;
				ATerm actualTerm = holder.getPlaceholder();
				
				long placeHolderDepth = this.getMaximumDepth(actualTerm);
				return placeHolderDepth > maxDepth ? placeHolderDepth + 1 : maxDepth + 1;
				
			default:
				
				return 0;
		}
	
	}

}
